<template>
  <div>
    <el-card style="height: 13%; line-height: 13%">
      <el-form
        style="
          display: flex;
          justify-content: space-between;
          align-items: center;
        "
      >
        <el-form-item label="用户名">
          <el-input
            @keyup.enter="getUserPages"
            placeholder="请输入用户名"
            v-model.trim="userOrName"
          ></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="getUserPages">搜索</el-button>
          <el-button size="default" @click="ResetInfo">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <el-card style="margin: 20px 0">
      <el-button type="primary" @click="addNewUser" v-has="`btn.User.add`">
        添加
      </el-button>
      <el-button
        type="danger"
        @click="anyDel"
        :disabled="idList.length < 1"
        v-has="`btn.User.remove`"
      >
        批量删除
      </el-button>
      <!-- Table -->
      <el-table
        :data="userInfo"
        border
        style="margin: 20px 0"
        tooltip-effect="dark"
        @selection-change="seleChange"
      >
        <el-table-column type="selection"></el-table-column>
        <el-table-column type="index" label="#"></el-table-column>
        <el-table-column prop="id" label="ID" align="center"></el-table-column>
        <el-table-column
          prop="username"
          label="用户名字"
          align="center"
        ></el-table-column>
        <el-table-column
          prop="name"
          label="用户名称"
          align="center"
        ></el-table-column>
        <el-table-column
          show-overflow-tooltip
          prop="roleName"
          label="用户角色"
          align="center"
        ></el-table-column>
        <el-table-column
          prop="createTime"
          label="创建时间"
          align="center"
        ></el-table-column>
        <el-table-column
          prop="updateTime"
          label="更新时间"
          align="center"
        ></el-table-column>
        <el-table-column label="操作" width="260px" align="center">
          <template #default="{ row }">
            <el-button
              type="primary"
              icon="User"
              size="small"
              @click="editRoles(row)"
              v-has="`btn.User.assgin`"
            >
              分配角色
            </el-button>
            <el-button
              type="primary"
              icon="Edit"
              size="small"
              plain
              @click="updateUser(row)"
              v-has="`btn.User.update`"
            >
              编辑
            </el-button>
            <el-popconfirm
              :title="`确认删除用户${row.username}?`"
              cancel-button-text="取消"
              confirm-button-text="确认"
              icon="InfoFilled"
              @confirm="deleteAdmin(row)"
            >
              <template #reference>
                <el-button
                  type="danger"
                  icon="Delete"
                  size="small"
                  v-has="`btn.User.remove`"
                ></el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <!-- Pagination -->
      <el-pagination
        size="default"
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[5, 10, 15]"
        :pager-count="7"
        layout="prev,pager,next,jumper,->,sizes,total"
        :total="total"
        :background="true"
        @size-change="sizeChange"
        @current-change="currentChange"
      ></el-pagination>
      <!-- drawer添加或修改 -->
      <el-drawer
        :title="userParams.id ? '修改用户信息' : '添加用户信息'"
        :model-value="drawerStatu"
        direction="rtl"
        destroy-on-close
        :before-close="handleClose"
      >
        <el-form ref="refForm" :model="userParams" :rules="rules" status-icon>
          <el-form-item label="用户姓名" prop="username">
            <el-input
              type="text"
              placeholder="请输入用户姓名"
              v-model="userParams.username"
            ></el-input>
          </el-form-item>
          <el-form-item label="用户昵称" prop="name">
            <el-input
              type="text"
              placeholder="请输入用户昵称"
              v-model="userParams.name"
            ></el-input>
          </el-form-item>
          <el-form-item
            type="text"
            label="用户密码"
            v-show="userParams.id ? false : true"
            :prop="userParams.id == '' ? 'password' : ''"
          >
            <el-input
              placeholder="请输入用户密码"
              v-model="userParams.password"
            ></el-input>
          </el-form-item>
          <el-form-item>
            <el-col :span="6"></el-col>
            <el-button type="primary" @click="responseAddorUpdate">
              提交
            </el-button>
            <el-col :span="5"></el-col>
            <el-button @click="clearnUserDraw(false)">重置</el-button>
            <el-col :span="6"></el-col>
          </el-form-item>
        </el-form>
      </el-drawer>
      <!-- drawer角色分配 -->
      <el-drawer v-model="drawer2" destory-on-close :before-close="d2Close">
        <template #header>
          <h3>用户角色分配</h3>
        </template>
        <template #default>
          <el-form>
            <el-form-item label="用户姓名">
              <el-input type="text" disabled :value="userParams.username" />
            </el-form-item>
            <el-form-item label="角色列表">
              <el-checkbox
                v-model="checkAll"
                :indeterminate="inminate"
                @change="checkAllChange"
              >
                全选
              </el-checkbox>
            </el-form-item>
            <el-form-item>
              <el-checkbox-group
                v-model="checkRoles"
                @change="rolesCheckchange"
              >
                <el-checkbox
                  v-for="i in lsg"
                  :key="i.id"
                  :label="i.roleName"
                  :value="i"
                ></el-checkbox>
              </el-checkbox-group>
            </el-form-item>
          </el-form>
        </template>
        <template #footer>
          <el-button plain @click="drawer2 = false">取消</el-button>
          <el-button type="primary" @click="updateRoles">确认</el-button>
        </template>
      </el-drawer>
    </el-card>
  </div>
</template>

<script lang="ts" setup name="index">
import { onMounted, reactive, ref } from 'vue'
import {
  getPageOfUserInfo,
  reqAnyDeleteUser,
  reqDeleteUser,
  reqGetRoles,
  reqUpdateOrAddUser,
  reqUpdateRoles,
} from '@/api/acl/user'
import {
  AddNewData,
  UpdateRoles,
  UserRecords,
  allRoles,
  assignRoles,
} from '@/api/acl/user/type'
import { ElMessage, ElMessageBox } from 'element-plus'
// 当前页码
let currentPage = ref(1)
//每页显示多少条
let pageSize = ref(5)
// 一共多少条
let total = ref(20)
//接收搜索框的值
let userOrName = ref('')
// 接收页面加载请求的基础用户信息
let userInfo = ref<UserRecords[]>([])
//添加或修改抽屉的状态
let drawerStatu = ref(false)
// ----角色修改数据---
let drawer2 = ref(false)
let checkAll = ref(false)
//全选框的不确定状态
let inminate = ref(true)
//已选中的值数据组
let checkRoles = ref<assignRoles>([])
//角色修改源数据
let lsg = ref<assignRoles>([])
//接收修改或添加的数据
let userParams = reactive<AddNewData>({
  id: '',
  name: '',
  roleName: '',
  username: '',
  password: '',
})
//ref获取vc实例去验证所有表单数据是否填写完整
const refForm = ref()
let idList = ref<number[]>([])
//定义初始化添加修改数据的方法公共
const clearnUserDraw = (esc?: any) => {
  // 通过是否传入esc来判断是否是退出添加或修改页面,以及是否需要删除当前id
  if (userParams.id) {
    if (esc) {
      Object.assign(userParams, {
        id: '',
        name: '',
        roleName: '',
        username: '',
        password: '',
      })
    } else {
      Object.assign(userParams, {
        name: '',
        roleName: '',
        username: '',
        password: '',
      })
    }
  } else {
    Object.assign(userParams, {
      id: '',
      name: '',
      roleName: '',
      username: '',
      password: '',
    })
  }
}
// 页面初始化请求数据
onMounted(() => {
  getUserPages()
})
//定义页面请求方法方便其他地方调用
const getUserPages = async () => {
  let result = await getPageOfUserInfo(
    currentPage.value,
    pageSize.value,
    userOrName.value,
    userOrName.value,
  )
  total.value = result.data.total
  userInfo.value = result.data.records
}
//重置搜索信息
const ResetInfo = () => {
  userOrName.value = ''
  getUserPages()
}
//显示条数发生改变时
const sizeChange = () => {
  getUserPages()
}
// 当前页发生改变时
const currentChange = () => {
  getUserPages()
}
//添加获取用户信息抽屉滑出
const addNewUser = () => {
  drawerStatu.value = true
}
//修改-获取用户信息-抽屉滑出
const updateUser = (row: UserRecords) => {
  drawerStatu.value = true
  Object.assign(userParams, row)
  userParams.password = ''
}
//添加或修改用户信息
const responseAddorUpdate = async () => {
  //判断是否验证通过
  const re = await refForm.value.validate((valid: any) => valid)
  if (re) {
    //判断是添加还是修改
    let updateOrAdd = userParams.id == '' ? true : false
    if (updateOrAdd) {
      // 添加回到第一页
      currentPage.value = 1
    } else {
      // 修改刷新页面
      window.location.reload()
    }
    //发送请求
    const result = await reqUpdateOrAddUser(userParams)
    if (result.code == 200) {
      ElMessage({
        type: 'success',
        message: updateOrAdd ? '添加成功' : '修改成功',
      })
      clearnUserDraw(true)
      drawerStatu.value = false
    } else {
      ElMessage({
        type: 'error',
        message: '用户姓名和昵称可能重复' + result.code,
      })
    }
  } else {
    ElMessage({ type: 'warning', message: '请输入完整信息' })
  }
  //重新请求数据
  getUserPages()
}
//退出前清空数据
const handleClose = () => {
  drawerStatu.value = false
  clearnUserDraw(true)
}
//d2close角色分配抽屉退出清除数据
const d2Close = () => {
  checkRoles.value = []
  lsg.value = []
  checkAll.value = false
  clearnUserDraw(true)
  drawer2.value = false
}
//全选按钮发生改变时
const checkAllChange = (val: boolean) => {
  checkRoles.value = val ? lsg.value : []
  inminate.value = false
}
//按钮组件发生改变时
const rolesCheckchange = (val: string[]) => {
  checkAll.value = lsg.value.length === val.length
  inminate.value = val.length > 0 && checkRoles.value.length < lsg.value.length
}
//获取基础信息
const editRoles = async (row: UserRecords) => {
  drawer2.value = true
  //这里不能直接赋值会影响源数据，需要使用assign复制第一层需要的数据
  Object.assign(userParams, row)
  const result = await reqGetRoles(row.id)
  lsg.value = result.data.allRolesList
  checkRoles.value = result.data.assignRoles
}
//保存修改用户角色信息
const updateRoles = async () => {
  let data: UpdateRoles = {
    userId: userParams.id as number,
    roleIdList: checkRoles.value.map((item: allRoles) => item.id),
  }
  const result = await reqUpdateRoles(data)
  if (result.code == 200) {
    getUserPages()
    drawer2.value = false
    ElMessage({ type: 'success', message: '分配角色成功' })
  } else {
    ElMessage({ type: 'success', message: '分配角色失败' + result.message })
  }
}
//删除用户信息
const deleteAdmin = async (row: UserRecords) => {
  const result = await reqDeleteUser(row.id)
  if (result.code == 200) {
    currentPage.value = 1
    getUserPages()
    ElMessage({ type: 'success', message: '删除成功' })
  } else {
    ElMessage({ type: 'error', message: result.message })
  }
}
// 收集select选择的数据
const seleChange = (val: UserRecords[]) => {
  idList.value = val.map((item) => item.id)
}
//批量删除用户信息
const anyDel = async () => {
  await ElMessageBox.confirm('正在批量删除用户,是否继续', 'Tip', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      const result = await reqAnyDeleteUser(idList.value as number[])
      if (result.code == 200) {
        getUserPages()
        ElMessage({
          type: 'success',
          message: '删除成功',
        })
      } else {
        ElMessage({
          type: 'error',
          message: '删除失败' + result.message,
        })
      }
    })
    .catch(() => {
      ElMessage({
        type: 'info',
        message: '取消删除',
      })
    })
}
//定义验证规则
const nameRule = (rule: any, value: any, callback: any) => {
  let ruless = /^[\u4E00-\u9FA5A-Za-z0-9]{5,}$/.test(value)
  if (!ruless) {
    callback(new Error('昵称必须大于等于5位字符,不能包含特殊字符'))
  }
  callback()
}
const userRule = (rule: any, value: any, callback: any) => {
  let ruless = /^[\u4E00-\u9FA5A-Za-z0-9]{5,}$/.test(value)
  if (!ruless) {
    callback(new Error('用户名必须为5位字符,不能包含特殊字符'))
  }
  callback()
}
const passWordRule = (rule: any, value: any, callback: any) => {
  let ruless = /^\S*(?=\S{6,})(?=\S*[!@#$%^&*? ])\S*$/.test(value)
  if (!ruless) {
    callback(new Error('密码必须为6位字符,且必须包含[!@#$%^&*? ]'))
  }
  callback()
}
//验证规则
const rules = reactive({
  username: [{ required: true, trigger: 'blur', validator: userRule }],
  name: [{ required: true, trigger: 'blur', validator: nameRule }],
  password: [
    {
      required: true,
      trigger: 'change',
      validator: passWordRule,
    },
  ],
})
</script>
<style lang="scss">
.is-dark,
.is-light {
  width: 500px;
}
</style>
<style scoped lang="scss"></style>
